package com.chl.legou.seckill.task;

import com.chl.legou.common.utils.IdWorker;
import com.chl.legou.common.utils.SystemConstants;
import com.chl.legou.seckill.dao.SeckillGoodsDao;
import com.chl.legou.seckill.po.SeckillGoods;
import com.chl.legou.seckill.po.SeckillOrder;
import com.chl.legou.seckill.po.SeckillStatus;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author chlong
 * @date 2022/12/16
 */
@Component
public class MultiThreadingCreateOrder {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillGoodsDao seckillGoodsDao;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private RedissonClient redissonClient;

    /**
     * 多线程下单
     */
    @Async
    public void createOrder() {

        //从队列中获取排队信息
        SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps(SystemConstants.SEC_KILL_USER_QUEUE_KEY).rightPop();
        if (seckillStatus != null) {
            //获取队列时间
            String time = seckillStatus.getTime();
            //获取用户名
            String username = seckillStatus.getUsername();
            //获取抢购商品
            Long id = seckillStatus.getGoodsId();

            //分布式锁
            RLock lock = redissonClient.getLock("seckillstock:" + id);

            try {
                //获得锁
                //waitTime：等待锁的时间
                //leaseTime：所得持有时间
                lock.tryLock(20,20, TimeUnit.SECONDS);

                // TODO 下单
                //获取商品数据
                SeckillGoods goods = (SeckillGoods) redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).get(id);
                //无数据，直接抛出异常
                if (goods == null || goods.getStockCount() <= 0) {
                    throw new RuntimeException("已售罄！");
                }
                //有库存，创建秒杀商品
                SeckillOrder seckillOrder = new SeckillOrder();
                seckillOrder.setId(idWorker.nextId());
                seckillOrder.setSeckillId(id);
                seckillOrder.setMoney(goods.getCostPrice());
                seckillOrder.setUserId(username);
                seckillOrder.setCreateTime(new Date());
                seckillOrder.setStatus("0");

                //模拟下单延时时间
                System.out.println("准备执⾏....");
                Thread.sleep(10000);
                System.out.println("开始执⾏....");

                //将秒杀商品存到redis中
                redisTemplate.boundHashOps(SystemConstants.SEC_KILL_ORDER_KEY).put(username, seckillOrder);
                //库存减少
                goods.setStockCount(goods.getStockCount() - 1);
                //判断当前商品是否还有库存
                if (goods.getStockCount() <= 0) {
                    //将数据同步到mysql中
                    seckillGoodsDao.updateById(goods);
                    //如果没有库存,则清空Redis缓存中该商品
                    redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).delete(id);
                } else {
                    //如果有库存，则直数据重置到Reids中
                    redisTemplate.boundHashOps(SystemConstants.SEC_KILL_GOODS_PREFIX + time).put(id, goods);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}
